home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / FWRunTyp / FWClaImp.cpp next >
Encoding:
Text File  |  1996-09-17  |  4.4 KB  |  163 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWClaImp.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef FWCLAIMP_H
  13. #include "FWClaImp.h"
  14. #endif
  15.  
  16. #ifdef FW_BUILD_MAC
  17. #pragma segment FW_ClassInfo
  18. #endif
  19.  
  20. //----------------------------------------------------------------------------------------
  21. //    IsKindOf
  22. //----------------------------------------------------------------------------------------
  23.  
  24. static FW_Boolean IsKindOf(FW_SClassInfoPtr derived, FW_SClassInfoPtr base)
  25. {
  26.     FW_Boolean result = false;
  27.     
  28.     if (base == derived)
  29.         result = true;
  30.     else
  31.     {
  32.         FW_SClassInfoPtr const *ancestors = derived->fAncestors;
  33.     
  34.         while (*ancestors != 0)
  35.         {
  36.             if (IsKindOf(*ancestors,base))
  37.             {
  38.                 result = true;
  39.                 break;
  40.             }
  41.             ancestors++;
  42.         }
  43.     }
  44.     return result;
  45. }
  46.  
  47. //----------------------------------------------------------------------------------------
  48. //    IsKindOf
  49. //----------------------------------------------------------------------------------------
  50.  
  51. static FW_Boolean OffsetToBase(FW_SClassInfoPtr derived, FW_SClassInfoPtr base, size_t& offset)
  52. {
  53.     FW_Boolean result = false;
  54.     
  55.     if (base == derived)
  56.     {
  57.         offset = 0;
  58.         result = true;
  59.     }
  60.     else
  61.     {
  62.         FW_SClassInfoPtr const *ancestors = derived->fAncestors;
  63.     
  64.         while (*ancestors != 0)
  65.         {
  66.             if (OffsetToBase(*ancestors, base, offset))
  67.             {
  68.                 offset += derived->fAncestorOffsets[ancestors - derived->fAncestors];
  69.                 result = true;
  70.                 break;
  71.             }
  72.             ancestors++;
  73.         }
  74.     }
  75.     
  76.     return result;
  77. }
  78.  
  79. //----------------------------------------------------------------------------------------
  80. //    FW_PrivDynamicCast
  81. //----------------------------------------------------------------------------------------
  82.  
  83. void* FW_PrivDynamicCast(const void* p, 
  84.                         FW_SClassInfoPtr fromDynamicClass, 
  85.                         FW_SClassInfoPtr fromStaticClass, 
  86.                         FW_SClassInfoPtr toStaticClass)
  87. {
  88.     size_t offset;
  89.     char *q = 0;
  90.     
  91.     if (p!=0)
  92.     {
  93.         if ((fromStaticClass == toStaticClass) && IsKindOf(fromDynamicClass, toStaticClass))
  94.         {
  95.             q = (char*) p;
  96.         }
  97.         else if (OffsetToBase(fromDynamicClass, toStaticClass, offset))
  98.         {
  99.             q = (char*) p;
  100.             q += offset;
  101.             FW_Boolean isKindOf = OffsetToBase(fromDynamicClass, fromStaticClass, offset);
  102.             if (!isKindOf)
  103.             {
  104.                 FW_PRIV_ASSERT(isKindOf);
  105.                 // If we get here, the declared pointer type was 
  106.                 // not consistent with the runtime type of the object!
  107.                 // That could only happen if somewhere else a bad cast 
  108.                 // (perhaps from a void*) was done.
  109.                 return 0;
  110.             }
  111.             q -= offset;
  112.         }
  113.     }
  114.  
  115.     return q;
  116. }
  117.  
  118. // Consider this code fragment:
  119. // 
  120. // template <class TActual, class TKnown, class TTarget>
  121. // foo()
  122. // {
  123. //     TKnown *p = new TActual();
  124. //     TTarget *t = dynamic_cast<TTarget*>(p);
  125. // }
  126. // 
  127. // TActual is the actual runtime type of the object.
  128. // TKnown is the compile-time type of the pointer variable that points
  129. //   to the object.
  130. // TTarget is the compile-time type that we are attempting to cast
  131. //   the pointer to.
  132. // 
  133. // Now, assume an operator IsKindOf(TDerived, TBase) that returns true
  134. // if class TDerived is derived from class TBase.
  135. // 
  136. // Given this, the result of the dynamic_cast above will be nonzero
  137. // if and only if IsKindOf(TActual, TTarget).  However, there are
  138. // interesting subvariations. In the following, assume
  139. // IsKindOf(TActual, TTarget):
  140. // 
  141. // The cast is a simple upcast if IsKindOf(TKnown, TTarget).  Upcasting
  142. // never needs a dynamic_cast, i.e. it can be done with a simple cast
  143. // (TTarget*).  Since ODF uses emulation, it is better to avoid
  144. // dynamic casts in this instance.
  145. // 
  146. // The cast is a standard downcast if IsKindOf(TTarget, TKnown).  This
  147. // is the most common case for dynamic_casts.
  148. // 
  149. // The cast is a sidecast if it is neither an upcast or a downcast, i.e.
  150. // a valid sidecast requires three conditions:
  151. // 
  152. //     IsKindOf(TActual, TTarget) && 
  153. //     !IsKindOf(TKnown, TTarget) &&
  154. //     !IsKindOf(TTarget, TKnown)
  155. // 
  156. // Sidecasts happen with mixin style programming.  Assume classes
  157. // CBase, MMixin, and CDerived, where CDerived inherits from both
  158. // CBase and MMixin.  A CBase* that points to a CDerived can be
  159. // successfully cast to a MMixin*, even if the code that contains
  160. // the dynamic_cast has no knowledge of the class CDerived, so
  161. // there is apparently no relationship between the known type and
  162. // the target type.
  163.